<?php

namespace service\impl;

use service\exception\ServiceException;
use service\ext\PageData;
use service\service\PracticeService;
use service\vo\practice\Practice;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class PracticeServiceImpl extends BaseImpl implements PracticeService
{

    //当前模块名称
    private static string $modeName = 'practice';

    /**
     * @inheritDoc
     */
    public function addPractice(Practice $practice): int
    {
        // TODO: Implement addPractice() method.
        $data = [
            self::$FIELD_COMMON_U_ID => $practice->getUserId(),
            self::$FIELD_PRACTICE_SUBJECT_COUNT => $practice->getSubjectCount(),
            self::$FIELD_PRACTICE_TIME => $practice->getTime(),
            self::$FIELD_PRACTICE_ADD_TIME => date("Y-m-d H:i:s"),
            self::$FIELD_PRACTICE_MODE => $practice->getMode(),
            self::$FIELD_PRACTICE_DIRECTION => $practice->getDirection(),
        ];

        return $this->getPracticeDb()->insertGetId($data);
    }

    /**
     * @inheritDoc
     * @throws DbException
     */
    public function deletePracticeById(int $id): int
    {
        // TODO: Implement deletePracticeById() method.
        return $this->getPracticeDb()
            ->where(self::$FIELD_COMMON_ID, $id)
            ->delete();
    }

    /**
     * @inheritDoc
     * @throws DbException
     */
    public function deletePracticeByIds(array $ids): int
    {
        // TODO: Implement deletePracticeByIds() method.
        return $this->getPracticeDb()->whereIn(self::$FIELD_COMMON_ID, $ids)->delete();
    }

    /**
     * @inheritDoc
     * @throws DbException
     */
    public function deletePracticeByUserId(int $userId): int
    {
        // TODO: Implement deletePracticeByUserId() method.
        return $this->getPracticeDb()
            ->where(self::$FIELD_COMMON_U_ID, $userId)
            ->delete();
    }

    /**
     * @inheritDoc
     * @throws DbException
     */
    public function deletePracticeByUserIds(array $userIds): int
    {
        // TODO: Implement deletePracticeByUserIds() method.
        return $this->getPracticeDb()
            ->whereIn(self::$FIELD_COMMON_U_ID, $userIds)
            ->delete();
    }

    /**
     * @inheritDoc
     */
    public function getPracticeById(int $id): Practice
    {
        // TODO: Implement getPracticeById() method.
        $po = $this->getPracticeDb()
            ->where(self::$FIELD_COMMON_ID, $id)
            ->findOrEmpty();
        if(empty($po)){
            throw new ServiceException(self::$modeName, self::ERROR_PRACTICE_NOT_EXISTS);
        }
        return $this->getPracticeVoFromPo($po);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     * @inheritDoc
     */
    public function searchPractices(int $currentPage, int $pageSize, array $filterCriteria, array $sorterCriteria): PageData
    {
        // TODO: Implement searchPractices() method.
        $filter = [];
        if (!empty($filterCriteria)) {
            foreach ($filterCriteria as $key => $value) {
                if (strcasecmp($key, self::$FILTER_USER_ID) == 0) {
                    //用户名
                    $filter[] = [self::$FIELD_COMMON_U_ID, "=", $value];
                } else if (strcasecmp($key, self::$FILTER_MODE) == 0) {
                    //用户名
                    $filter[] = [self::$FIELD_PRACTICE_MODE, "=", $value];
                } else if (strcasecmp($key, self::$FILTER_DIRECTION) == 0) {
                    //用户名
                    $filter[] = [self::$FIELD_PRACTICE_DIRECTION, "=", $value];
                } elseif (strcasecmp($key, self::$FILTER_ADD_TIME) == 0) {
                    //时间
                    $betweenTime = makeBetween($value['start'], $value['end']);
                    $filter[] = [self::$FIELD_PRACTICE_ADD_TIME, $betweenTime[0], $betweenTime[1]];
                }
            }
        }

        //构建排序条件
        $sort = [];
        if (!empty($sorterCriteria)) {
            foreach ($sorterCriteria as $key => $value) {
                if (strcasecmp($key, self::$SORT_ID) == 0) {
                    $sort[self::$FIELD_COMMON_ID] = $value ? self::$SORT_VALUE_ASC : self::$SORT_VALUE_DESC;
                }
            }
        }
        $count = $this->getPracticeDb()
            ->where($filter)
            ->count();

        $list = $this->getPracticeDb()
            ->where($filter)
            ->order($sort)
            ->limit($pageSize)
            ->page($currentPage)
            ->select();

        $dataList = [];
        foreach ($list as $po) {
            $dataList[] = $this->getPracticeVoFromPo($po);
        }

        $pageData = new PageData();
        $pageData->setData($dataList);
        $pageData->setCount($count);

        return $pageData;
    }

    /**
     * 获取Practice对象
     */
    private function getPracticeVoFromPo($po): Practice
    {
        $vo = new Practice();
        $vo->setId($po[self::$FIELD_COMMON_ID]);
        $vo->setUserId($po[self::$FILTER_USER_ID]);
        $vo->setAddTime($po[self::$FIELD_PRACTICE_ADD_TIME]);
        $vo->setMode($po[self::$FIELD_PRACTICE_MODE]);
        $vo->setDirection($po[self::$FIELD_PRACTICE_DIRECTION]);
        $vo->setTime($po[self::$FIELD_PRACTICE_TIME]);
        $vo->setSubjectCount($po[self::$FIELD_PRACTICE_SUBJECT_COUNT]);
        return $vo;
    }
}